package com.spzx.cart.service.impl;

import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.spzx.cart.domain.CartInfo;
import com.spzx.cart.service.ICartService;
import com.spzx.common.core.constant.SecurityConstants;
import com.spzx.common.core.context.SecurityContextHolder;
import com.spzx.common.core.domain.R;
import com.spzx.common.core.exception.ServiceException;
import com.spzx.product.api.RemoteProductService;
import com.spzx.product.domain.ProductSku;
import com.spzx.product.domain.SkuPrice;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * BelongProject: spzx-parent
 * BelongPackage: com.spzx.cart.service.impl
 * Description:
 *
 * @Author 段鑫涛
 * @Create 2025/6/2 19:32
 * @Version 1.0
 */
@Service
@Slf4j
public class CartServiceImpl implements ICartService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private RemoteProductService remoteProductService;

    private String getCartKey(Long userId) {
        //定义key user:userId:cart
        return "user:cart:" + userId;
    }

    @Override
    public void addToCart(Long skuId, Integer skuNum) {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();

        //1.构建“用户”购物车hash结构key  user：用户ID：cart
        String cartKey = getCartKey(userId);

        //2.创建Hash结构绑定操作对象（方便对hash进行操作）
        BoundHashOperations<String, String, CartInfo> hashOps = redisTemplate.boundHashOps(cartKey);

        //3.判断用户购物车中是否包含该商品 如果包含：数量进行累加(某件商品数量上限99) 不包含：新增购物车商品
        String hashKey = skuId.toString();
        Integer threshold = 99;
        if( hashOps.hasKey(hashKey)){
            //4.1 说明该商品在购物车中已有，对数量进行累加 ，不能超过指定上限99
            CartInfo cartInfo = hashOps.get(hashKey);
            int totalCount = cartInfo.getSkuNum() + skuNum;
            cartInfo.setSkuNum(totalCount > threshold ? threshold : totalCount);
             hashOps.put(hashKey,cartInfo);
        }else {
            //4.判断购物车商品种类（不同SKU）总数大于50件
             if(hashOps.size() >= 50){
                  throw new RuntimeException("购物车商品种类（不同SKU）总数不能超过50件");
             }

            //5. 说明购物车没有该商品，构建购物车对象，存入Redis
             CartInfo cartInfo = new CartInfo();
             cartInfo.setUserId(userId);
             cartInfo.setSkuNum(skuNum > threshold ? threshold : skuNum);
             cartInfo.setUpdateTime(new Date());
             cartInfo.setCreateTime(new Date());

            //5.1 远程调用商品服务获取商品sku基本信息
            R<ProductSku> productSkuResult = remoteProductService.getProductSku(skuId, SecurityConstants.INNER);
            if (R.FAIL == productSkuResult.getCode()) {
                throw new ServiceException(productSkuResult.getMsg());
            }
            ProductSku productSku = productSkuResult.getData();
            cartInfo.setSkuId(skuId);
            cartInfo.setSkuName(productSku.getSkuName());
            cartInfo.setThumbImg(productSku.getThumbImg());

            //5.2 远程调用商品服务获取商品实时价格
            R<SkuPrice> skuPriceResult = remoteProductService.getSkuPrice(skuId, SecurityConstants.INNER);
            if (R.FAIL == skuPriceResult.getCode()) {
                throw new ServiceException(skuPriceResult.getMsg());
            }
            SkuPrice skuPrice = skuPriceResult.getData();
            cartInfo.setCartPrice(skuPrice.getSalePrice());
            cartInfo.setSkuPrice(skuPrice.getSalePrice());

            //5.3 将购物车商品存入Redis
            hashOps.put(hashKey, cartInfo);
        }
    }

    @Override
    public List<CartInfo> getCartList() {
        // 获取当前用户的ID
        Long userId = SecurityContextHolder.getUserId();
        // 根据用户ID获取购物车在Redis中的键
        String cartKey = this.getCartKey(userId);
        // 从Redis中获取购物车中的所有商品信息
        List<CartInfo> cartInfoList = (List<CartInfo>)redisTemplate.opsForHash().values(cartKey);
        // 检查购物车是否为空
        if (!CollectionUtils.isEmpty(cartInfoList)){
            // 对购物车中的商品按照创建时间降序排序
            List<CartInfo> infoList = cartInfoList.stream()
                    .sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()))
                    .collect(Collectors.toList());
            // 提取所有商品的SKU ID
            List<Long> skuIdList = infoList.stream().map(CartInfo::getSkuId).collect(Collectors.toList());
            // 调用远程服务获取SKU价格列表
            R<List<SkuPrice>> SkuPriceListResult = remoteProductService.getSkuPriceList(skuIdList, SecurityConstants.INNER);
            // 检查远程服务调用是否成功
            if (R.FAIL == SkuPriceListResult.getCode()) {
                throw new ServiceException(SkuPriceListResult.getMsg());
            }
            // 将获取到的SKU价格信息转换为Map，便于后续查询
            Map<Long, BigDecimal> skuIdToPriceMap = SkuPriceListResult.getData().stream().collect(Collectors.toMap(SkuPrice::getSkuId, SkuPrice::getSalePrice));
            // 为每个购物车商品设置价格信息
            infoList.forEach(item -> {
                item.setSkuPrice(skuIdToPriceMap.get(item.getSkuId()));
            });
            // 返回填充了价格信息的购物车商品列表
            return infoList ;
        }
        // 如果购物车为空，返回空列表
        return new ArrayList<>();
    }

    @Override
    public void deleteCart(Long skuId) {
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        hashOperations.delete(skuId.toString());
    }

    @Override
    public void checkCart(Long skuId, Integer isChecked) {
        // 获取当前用户的ID
        Long userId = SecurityContextHolder.getUserId();
        // 构造购物车信息的Redis键
        String cartKey = getCartKey(userId);
        // 获取Redis中购物车信息的Hash操作对象
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        // 检查购物车中是否存在指定的SKU商品
        if (hashOperations.hasKey(skuId.toString())){
            // 从购物车中获取指定SKU的商品信息
            CartInfo cartInfo = hashOperations.get(skuId.toString());
            // 更新商品的选中状态
            cartInfo.setIsChecked(isChecked);
            // 将更新后的商品信息重新放入购物车
            hashOperations.put(skuId.toString(), cartInfo);
        }
    }

    @Override
    public void allCheckCart(Integer isChecked) {
        // 获取当前用户的ID
        Long userId = SecurityContextHolder.getUserId();
        // 根据用户ID生成购物车在Redis中的唯一键
        String cartKey = getCartKey(userId);
        // 获取Redis中购物车信息的操作对象
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        // 从Redis中获取购物车信息列表
        List<CartInfo> cartInfoList = hashOperations.values();
        // 遍历购物车信息列表，更新每个商品的选中状态
        cartInfoList.forEach( item -> {
            // 根据商品ID获取购物车信息
            CartInfo cartInfo = hashOperations.get(item.getSkuId().toString());
            // 设置商品的选中状态
            cartInfo.setIsChecked(isChecked);
            // 更新Redis中的购物车信息
            hashOperations.put(item.getSkuId().toString(), cartInfo);
        });
    }

    @Override
    public void clearCart() {
        // 获取当前登录用户的id
        Long userId = SecurityContextHolder.getUserId();
        String cartKey = getCartKey(userId);
        //获取缓存对象
        redisTemplate.delete(cartKey);
    }

    @Override
    public List<CartInfo> getCartCheckedList(Long userId) {
        // 初始化购物车列表
        List<CartInfo> cartInfoList = new ArrayList<>();
        // 获取用户的购物车键
        String cartKey = this.getCartKey(userId);
        // 从Redis中获取购物车信息列表
        List<CartInfo> cartCachInfoList = redisTemplate.opsForHash().values(cartKey);
        // 检查购物车信息列表是否为空
        if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            // 遍历购物车信息列表
            for (CartInfo cartInfo : cartCachInfoList) {
                // 获取选中的商品！
                if (cartInfo.getIsChecked().intValue() == 1) {
                    // 将选中的商品添加到购物车列表中
                    cartInfoList.add(cartInfo);
                }
            }
        }
        // 返回选中的商品列表
        return cartInfoList;
    }

    @Override
    public Boolean updateCartPrice(Long userId) {
        // 获取用户购物车在Redis中的键
        String cartKey = getCartKey(userId);
        // 获取购物车信息的Hash操作对象
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        // 从Redis中获取购物车信息列表
        List<CartInfo> cartCachInfoList = hashOperations.values();
        // 检查购物车信息列表是否为空
        if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            // 遍历购物车信息列表
            for (CartInfo cartInfo : cartCachInfoList) {
                // 检查商品是否被选中
                if (cartInfo.getIsChecked().intValue() == 1) {
                    // 调用远程服务获取商品的SKU价格信息
                    SkuPrice skuPrice = remoteProductService.getSkuPrice(cartInfo.getSkuId(), SecurityConstants.INNER).getData();
                    // 更新购物车中商品的价格信息
                    cartInfo.setCartPrice(skuPrice.getSalePrice());
                    cartInfo.setSkuPrice(skuPrice.getSalePrice());
                    // 将更新后的购物车信息放回Redis
                    hashOperations.put(cartInfo.getSkuId().toString(), cartInfo);
                }
            }
        }
        // 返回操作成功
        return true;
    }

    @Override
    public Boolean deleteCartCheckedList(Long userId) {
        // 根据用户ID获取购物车信息的键
        String cartKey = getCartKey(userId);
        // 获取Redis中与购物车键关联的哈希操作对象
        BoundHashOperations<String, String, CartInfo> hashOperations = redisTemplate.boundHashOps(cartKey);
        // 从Redis中获取购物车信息列表
        List<CartInfo> cartCachInfoList = hashOperations.values();
        // 检查购物车信息列表是否为空
        if (!CollectionUtils.isEmpty(cartCachInfoList)) {
            // 遍历购物车信息列表
            for (CartInfo cartInfo : cartCachInfoList) {
                // 获取选中的商品！
                if (cartInfo.getIsChecked().intValue() == 1) {
                    // 删除Redis中选中的商品信息
                    hashOperations.delete(cartInfo.getSkuId().toString());
                }
            }
        }
        // 返回删除成功
        return true;

    }
}
